package utils

import (
	"errors"
	"sync"
	"time"
)

// 雪花算法结构体
type Worker struct {
	Mu        sync.Mutex
	Timestamp int64
	WorkerId  int64
	Number    int64
}

// 雪花算法生成ID
const (
	workerBits  uint8 = 6
	numberBits  uint8 = 8
	workerMax   int64 = -1 ^ (-1 << workerBits)
	numberMax   int64 = -1 ^ (-1 << numberBits)
	timeShift   uint8 = workerBits + numberBits
	workerShift uint8 = numberBits
	startTime   int64 = 1325705533000
)

// 生成ID
func NewWorker(workerId int64) (*Worker, error) {
	if workerId < 0 || workerId > workerMax {
		return nil, errors.New("ID生成数量超出")
	}
	// 生成一个新节点
	return &Worker{
		Timestamp: 0,
		WorkerId:  workerId,
		Number:    0,
	}, nil
}

// 获取ID
func (w *Worker) GetId() int64 {
	w.Mu.Lock()
	defer w.Mu.Unlock()
	now := time.Now().UnixNano() / 1e6
	if w.Timestamp == now {
		w.Number++
		if w.Number > numberMax {
			for now <= w.Timestamp {
				now = time.Now().UnixNano() / 1e6
			}
		}
	} else {
		w.Number = 0
		w.Timestamp = now
	}
	ID := int64((now-startTime)<<timeShift | (w.WorkerId << workerShift) | (w.Number))
	return ID
}
